Saltar al contenido principal

Wallets – Referencia del Go SDK

Descripción general​

El módulo wallet en el Go SDK es responsable de:

  • Representar un wallet de ULedger (UL_Wallet)
  • Generar wallets a partir de mnemonics, keys o JSON
  • Persistir wallets en disco (archivos .ukey)
  • Reconstruir wallets desde datos almacenados
  • Gestionar la entropía BIP-39 y los mnemonics

Un wallet combina:

  • Una dirección (derivada de la clave pública)
  • Grupos de permisos (AuthGroups)
  • Un par de claves criptográficas (crypto.ULKey) usado para firmar transactions

Tipos principales​

UL_Wallet​

type UL_Wallet struct {
Address string `json:"address"`
Enabled bool `json:"enabled"`
Parent string `json:"parent"`
AuthGroups map[string]UL_AuthPermission `json:"authGroups"`
key crypto.ULKey `json:"-"`
}
  • Address – dirección del wallet utilizada en la cadena y en las APIs.
  • Enabled – indica si este wallet está activo actualmente.
  • Parent – dirección del wallet padre (para jerarquías padre/hijo).
  • AuthGroups – grupos de permisos lógicos.
  • key – clave criptográfica en memoria (no serializada).

UL_AuthPermission​

type UL_AuthPermission struct {
Create bool `json:"create"`
Read bool `json:"read"`
Update bool `json:"update"`
Delete bool `json:"delete"`
}

Define permisos CRUD para un nombre de grupo determinado (por ejemplo, "Wallet" o "wallet").

WalletData (estructura de persistencia)​

type WalletData struct {
Address string `json:"address"`
Enabled bool `json:"enabled"`
Parent string `json:"parent"`
AuthGroups map[string]UL_AuthPermission `json:"authGroups"`
Mnemonic string `json:"mnemonic"`
KeyType crypto.KeyType `json:"keyType"`
PublicKeyHex string `json:"publicKeyHex"`
PrivateKeyHex string `json:"privateKeyHex"`
}

Esta es la estructura JSON utilizada al guardar/cargar wallets (por ejemplo, desde archivos .ukey).

Constante de nombre de grupo de autenticación​

const (
WALLET_GROUP_NAME = "wallet"
)

Un nombre de grupo predeterminado que puede usarse para permisos relacionados con wallets.


Acceso a la key​

(*UL_Wallet).GetKey​

func (w *UL_Wallet) GetKey() crypto.ULKey

Devuelve el crypto.ULKey subyacente, que se utiliza para:

  • Determinar el tipo de key (GetType)
  • Obtener el hex de la clave pública/privada
  • Firmar los compromisos de transactions

Esto es lo que usa la sesión de transaction cuando llama a wallet.GetKey().SignData(...).


Creación de wallets​

FromJson​

func FromJson(data string, passphrase string) (*UL_Wallet, error)

Crea un UL_Wallet a partir de una cadena JSON que coincide con la estructura WalletData.

Qué hace:

  1. Deserializa data en WalletData.

  2. Crea un UL_Wallet con:

    • Address, Parent, Enabled, AuthGroups del JSON.
  3. Usa KeyType para obtener un crypto.ULKey concreto.

  4. Llama a:

    • GeneratePublicKeyFromHex(false, PublicKeyHex)
    • GeneratePrivateKeyFromHex(PrivateKeyHex)

Si la reconstrucción de la key falla, se devuelve un error.

Usado en tu CLI de transactions para cargar wallets desde archivos (o JSON).


GetWalletFromHex​

func GetWalletFromHex(
publicKeyHex, privateKeyHex string,
keyType crypto.KeyType,
) (UL_Wallet, error)

Crea un wallet directamente a partir del material de key proporcionado.

Pasos:

  1. Obtiene un crypto.ULKey para el keyType dado.
  2. Llama a GeneratePublicKeyFromHex(false, publicKeyHex).
  3. Llama a GeneratePrivateKeyFromHex(privateKeyHex).
  4. Calcula la dirección como ParseAddress(key.GetPublicKeyHex(false)).
  5. Devuelve un UL_Wallet con:
    • Address establecido en la dirección derivada
    • key establecido en la key construida

Desde las pruebas:

  • Key válida → dirección no vacía

  • Puedes verificar que la clave privada va y viene correctamente:

    if !strings.EqualFold(wallet.key.GetPrivateKeyHex(), privateKeyHex) {
    // discrepancia
    }

ParseAddress​

func ParseAddress(publicKeyHex string) string

Deriva la dirección del wallet a partir de la clave pública codificada en hex.

Algoritmo:

  1. Convierte el hex de la clave pública a minúsculas.
  2. Calcula sha256 sobre los bytes de la cadena en minúsculas.
  3. Codifica el hash como hex.

Esta función determinista se usa tanto al generar nuevos wallets como al reconstruir a partir de claves existentes.


GenerateFromMnemonic​

func GenerateFromMnemonic(
mnemonic string,
passphrase string,
keyType crypto.KeyType,
) (UL_Wallet, error)

Crea un wallet a partir de un mnemonic BIP-39.

Flujo:

  1. Llama a MnemonicToSeed(mnemonic, passphrase) para obtener una semilla.
  2. Crea un crypto.ULKey basado en keyType.
  3. Llama a GenerateKeyFromSeed(seed) en la key.
  4. Deriva la dirección del wallet mediante ParseAddress(key.GetPublicKeyHex(false)).
  5. Devuelve un UL_Wallet con:
    • Address establecido
    • key poblado (otros campos como Enabled, Parent, AuthGroups se completan después)

GenerateNewWallet​

func GenerateNewWallet(
passphrase string,
keyType crypto.KeyType,
parent string,
authGroups map[string]UL_AuthPermission,
entropy Entropy,
) (UL_Wallet, string, error)

Genera un nuevo wallet + mnemonic.

Pasos:

  1. Llama a GenerateMnemonic(entropy) para obtener una frase BIP-39.

  2. Llama a GenerateFromMnemonic(mnemonic, passphrase, keyType) para derivar una key.

  3. Establece:

    • wallet.Parent = parent
    • wallet.Enabled = true
    • wallet.AuthGroups = authGroups
  4. Devuelve:

    • UL_Wallet
    • mnemonic (string)
    • error

Esto es lo que el comando CLI de "Generar Wallet" envuelve en última instancia.


Guardar y cargar wallets​

(*UL_Wallet).SaveToFile​

func (w *UL_Wallet) SaveToFile(
filePath string,
mnemonic string,
includePrivateKey bool,
) error

Persiste un wallet en un archivo .ukey.

Comportamiento:

  • Asegura que la ruta del archivo termine con .ukey.

  • Construye un WalletData con:

    • Address, Parent, Enabled
    • KeyType, Mnemonic
    • PublicKeyHex
    • AuthGroups
  • Incluye PrivateKeyHex solo si includePrivateKey == true.

  • Escribe el JSON en disco con permisos 0600.

Esto te permite elegir entre:

  • Archivos de wallet "completos" (incluyen la clave privada)
  • Archivos de wallet "solo públicos" (sin clave privada, para distribución más segura)

LoadFromFile​

func LoadFromFile(
filePath string,
passphrase string,
) (UL_Wallet, error)

Lee un archivo .ukey y reconstruye un UL_Wallet.

Orden de prioridad:

  1. Mnemonic presente → GenerateFromMnemonic(mnemonic, passphrase, KeyType)

  2. Si no, si clave privada presente:

    • GetHasherByType(KeyType)
    • GetKeyByType(KeyType, hasher)
    • GeneratePublicKeyFromHex(false, PublicKeyHex)
    • GeneratePrivateKeyFromHex(PrivateKeyHex)
  3. Si no (sin mnemonic, sin clave privada):

    • Usa solo KeyType + PublicKeyHex (estilo solo-lectura)
    • Sin clave privada en memoria

Esto te permite:

  • Recuperar wallets completos desde frases semilla
  • Reconstruir wallets desde pares de claves conocidos
  • Cargar wallets de solo lectura desde claves públicas

Utilidades de entropía y mnemonic​

El segundo archivo mostrado es la capa auxiliar BIP-39 usada por GenerateNewWallet y GenerateFromMnemonic.

Tipo Entropy y constantes​

type Entropy int

const (
Entropy128 Entropy = 128
Entropy160 Entropy = 160
Entropy192 Entropy = 192
Entropy224 Entropy = 224
Entropy256 Entropy = 256

// Default entropy size (256 bits = 24 words)
DefaultEntropy = Entropy256
)
  • La entropía se expresa en bits y se corresponde con conteos de palabras:
    • 128 → 12 palabras
    • 160 → 15 palabras
    • 192 → 18 palabras
    • 224 → 21 palabras
    • 256 → 24 palabras

MakeEntropy​

func MakeEntropy(i int) Entropy

Convierte un entero (128, 160, 192, 224, 256) en la constante Entropy correspondiente, usando DefaultEntropy por defecto en cualquier otro caso.


GenerateMnemonic​

func GenerateMnemonic(entropySize Entropy) (string, error)

Genera una frase mnemonic BIP-39.

  • Tamaños de entropía válidos: múltiplos de 32 entre 128 y 256 bits.
  • Internamente:
    • Usa crypto/rand para generar entropía.
    • Usa bip39.NewMnemonic(entropy) para derivar la frase.

Usado por GenerateNewWallet.


MnemonicToSeed​

func MnemonicToSeed(
mnemonic string,
passphrase string,
) ([]byte, error)

Convierte un mnemonic BIP-39 + passphrase opcional en una semilla.

  • Valida el mnemonic mediante bip39.IsMnemonicValid.
  • Usa bip39.NewSeed(mnemonic, passphrase).

Usado por GenerateFromMnemonic.


Helpers de validación e inspección​

func ValidateMnemonic(mnemonic string) bool
func GetWordList() []string
func GetWordIndex(word string) (int, error)
func GetWordCount(mnemonic string) int
func GetEntropySize(mnemonic string) (Entropy, error)
  • ValidateMnemonic – verifica si una frase es BIP-39 válida.
  • GetWordList – devuelve el diccionario BIP-39 subyacente.
  • GetWordIndex – encuentra el índice de una palabra en esa lista.
  • GetWordCount – número de palabras en una frase.
  • GetEntropySize – deriva el tamaño de entropía según el conteo de palabras (12/15/18/21/24).

Ejemplo: creación programática de wallet (referencia)​

No es un tutorial completo, solo un esbozo de uso vinculado a la API anterior:

package main

import (
"fmt"

"github.com/ULedgerInc/go-sdk/pkg/crypto"
"github.com/ULedgerInc/go-sdk/pkg/wallet"
)

func main() {
passphrase := "optional-passphrase"

auth := map[string]wallet.UL_AuthPermission{
"Wallet": {Create: true, Read: true, Update: true, Delete: false},
}

w, mnemonic, err := wallet.GenerateNewWallet(
passphrase,
crypto.KeyTypeSecp256k1,
"", // parent
auth, // auth groups
wallet.Entropy256, // 24 words
)
if err != nil {
panic(err)
}

fmt.Println("Address:", w.Address)
fmt.Println("Mnemonic:", mnemonic)

if err := w.SaveToFile("./wallets/my-wallet.ukey", mnemonic, true); err != nil {
panic(err)
}
}

Luego puedes cargarlo con `LoadFromFile` o parsear el JSON almacenado y usar `FromJson`.